/*
 * Author: Xingbo Wang, Yaqin Yang, Ying Yang
 * Database Project
 * Time : spring 2011
 * */

package database;

//collision test


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.*;

import database.impl.Record;

/*
 *Responsibility
 * 1. store all the data file information : open, close, loaded, unload, etc.
 * test.
 */

public class DataManager {
	// load all the files into memory.
	private static Map<String,DataFile> openedFiles;//file name map corresponding dataFile object.
	public static Map<String, DataFile> getOpenedFiles() {
		return openedFiles;
	}

	public static void setOpenedFiles(Map<String, DataFile> openedFiles) {
		DataManager.openedFiles = openedFiles;
	}

	static {
		openedFiles = new HashMap<String,DataFile>();
	}



	public DataManager() {
	}

	// create an empty table
	//check: fileName and descriptor is null or not; maximum length should be less than 1000; each length should be longer than 0.
	//column duplicate or not need not be checked since the structure is Map the key can not be duplicated.
	public static DataFile createFile(String fileName,
			Map<String, Integer> descriptor) {
		Collection<Integer> c = descriptor.values();
		// obtain an Iterator for Collection
		Iterator<Integer> itr = c.iterator();
		// iterate through HashMap values iterator
	   if(fileName.trim().length()==0){
		   String e="Please input a fileName";
		   throw new IllegalArgumentException(e);
	   }
	   if(descriptor.size()==0){
		   String e="please input a descriptor";
		   throw new IllegalArgumentException(e);
	   }
		while (itr.hasNext()) {
		Integer temp=(Integer) itr.next();
			if ((temp > 1000)) {
				String e = "the maximum length should be less than 1000";
				throw new IllegalArgumentException(e);
			}
			if (temp<=0) {
				String e = "the maximum length should be more than 0";
				throw new IllegalArgumentException(e);
			}
		}
		

		if (openedFiles.containsKey(fileName)) {// check if already in memory
			throw new IllegalArgumentException();
		}
		DataFile df = new DataFile(fileName);// create DataFile class
		df.setSchema(descriptor); // setSchema
		openedFiles.put(fileName, df); // add fileName to set
		return df;
	}

	// load file to memory
	// exception IllegalArgumentException
	// 1. have already been loaded into files
	// 2. can't find the file
	public static DataFile restoreFile(String fileName) {
		
		if (openedFiles.containsKey(fileName)) {// check if already in memory
			throw new IllegalArgumentException();
		}
		DataFile datafile = new DataFile(fileName);
		Vector<Record> records = datafile.getRecords();
		try {
			
			//restore file contents
			FileInputStream fis = new FileInputStream(fileName);
			ObjectInputStream ois = new ObjectInputStream(fis);
			
			int recordSize = ois.readInt();
//			datafile = (DataFile)(ois.readObject());			
//			System.out.println("vector number: " + vectorNumber);
			datafile.setValidNum(ois.readInt());
//			records = ((Vector<Record>) ois.readObject());
			for (int i = 0; i < recordSize; i++) {
				records.add((Record) ois.readObject());
			}
			System.out.println("records: " + records.size());
			fis.close();
			ois.close();
			
			//restore file information
			FileInputStream fis1 = new FileInputStream(fileName + "_info");
			ObjectInputStream ois1 = new ObjectInputStream(fis1);
			@SuppressWarnings("unchecked")
			Map<String, String> readObject = (Map<String, String>) ois1
					.readObject();
			datafile.setIndexNameMap(readObject);

			@SuppressWarnings("unchecked")
			Map<String, Integer> readObject2 = (Map<String, Integer>) ois1
					.readObject();
			datafile.setSchema(readObject2);
			
			@SuppressWarnings("unchecked")
			Vector<Boolean> readObject3 = (Vector<Boolean>) ois1.readObject();
			datafile.setBitmap(readObject3);
			
			int validRecord = 0;
			Vector<Boolean> bitmap = datafile.getBitmap();
			for (int i = 0; i < bitmap.size(); i++) {
				if (bitmap.elementAt(i)) {					
					++validRecord;
				}
			}
			datafile.setRecordNum(validRecord);
			
			fis1.close();
			ois.close();
			
			openedFiles.put(fileName, datafile);
		} catch (FileNotFoundException e) {
			System.out.println("File name not exist.");
			throw new IllegalArgumentException();
		} catch (IOException e) {
			System.out.println("IO exception.");
			throw new IllegalArgumentException();
		} catch (Exception e) {
			System.out.println("Exception");			
		}
		return datafile;
	}

	// print record contents
	public static String print(Map<String, String> record) {
		Iterator it = record.entrySet().iterator();
		String output = "";
		while (it.hasNext()) {
			Map.Entry pairs = (Map.Entry) it.next();
			if (pairs.getValue() != null) {
				output = output + "\t"+(pairs.getKey() + ": " + pairs.getValue())
						+ "\n";
			}
		}
		System.out.println(output);

		return output;
	}

	// close application
	public static void exit() {
		DataFile df = null ;
		Iterator ite = openedFiles.values().iterator();
		while (ite.hasNext()) {
			df=(DataFile) ite.next();
			df.dumpFile();		
		
			for (Map.Entry<String, Index> entry :df.getIndices().entrySet()) {
				entry.getValue().setValidNumber(df.getValidNum()); 
				entry.getValue().dumpIndex();
			}
		}
		openedFiles.clear();
		System.out.println("exist successful");
	}
}
